#include <gtest/gtest.h>
#include <vendor_global.h>
#include "xcom_parser.h"

namespace protocol {
class XComParserTest : public ::testing::Test {
public:
	void SetUp() override
	{
		load = xcomParser_.LoadXComFile(
			VENDOR_TEST_PATH + "/test_xcom_parser.xcom");
	}

	void TearDown() override
	{
		xcomParser_.Clear();
		load = false;
	}

	XComParser xcomParser_;
	bool load = false;
};

TEST_F(XComParserTest, WrapToken)
{
	XComParser xcomParser;
	const std::string line = "```xcom";
	int pos = 0;
	EXPECT_EQ(xcomParser.WrapToken(line, pos), "```");
	EXPECT_EQ(xcomParser.WrapToken(line, pos), "xcom");
}

TEST_F(XComParserTest, LoadXComFile) { EXPECT_TRUE(load); }

TEST_F(XComParserTest, LoadXComFileNode)
{
	std::shared_ptr<protocol::XComNode> xcomNode =
		xcomParser_.GetXComNode("P0046F56202C21000T");
	EXPECT_NE(xcomNode, nullptr);
	EXPECT_EQ(xcomNode->GetId(), "P0046F56202C21000T");
	EXPECT_EQ(xcomNode->GetName(), "雷优/单相电表/阀控");
	HTELINK_LOG_INFO(xcomNode->GetTemplate().c_str());
}

TEST_F(XComParserTest, LoadXComFileFlow)
{
	std::shared_ptr<protocol::XComNode> xcomNode =
		xcomParser_.GetXComNode("P0046F56202C21000T");

	const Flow_t &readFlow = xcomNode->GetFlow("read");
	const Flow_t &writeFlow = xcomNode->GetFlow("write");
	EXPECT_EQ(readFlow.procList.size(), 2);
	EXPECT_EQ(readFlow.procList.at(0).call, "send");
	EXPECT_EQ(readFlow.procList.at(1).call, "recv");
	EXPECT_EQ(writeFlow.procList.size(), 2);
	EXPECT_EQ(writeFlow.procList.at(0).call, "send");
	EXPECT_EQ(writeFlow.procList.at(1).call, "recv");
}

TEST_F(XComParserTest, LoadXComFileFlow2)
{
	std::shared_ptr<protocol::XComNode> xcomNode =
		xcomParser_.GetXComNode("P056934A925C21000T");

	const Flow_t &readFlow = xcomNode->GetFlow("read");
	EXPECT_EQ(readFlow.procList.size(), 2);
	EXPECT_EQ(readFlow.procList.at(0).call, "send");
	EXPECT_EQ(readFlow.procList.at(1).call, "recv");

	const Flow_t &flow = xcomNode->GetFlow("12L");
	EXPECT_EQ(flow.procList.size(), 2);
	EXPECT_EQ(flow.procList.at(0).call, "send");
	EXPECT_EQ(flow.procList.at(1).call, "recv");
}

TEST_F(XComParserTest, LoadXComFileFunctions)
{
	std::shared_ptr<protocol::XComNode> xcomNode =
		xcomParser_.GetXComNode("P0046F56202C21000T");
	const FuncParam_t &funcpoints = xcomNode->GetFuncParam("11X");
	EXPECT_EQ(funcpoints.flow, "read");
	EXPECT_EQ(funcpoints.resultExpr->ToExprString(), "$float($data)");
	EXPECT_EQ(funcpoints.vars.size(), 3);

	EXPECT_NE(funcpoints.vars.find("reg"), funcpoints.vars.end());
	EXPECT_NE(funcpoints.vars.find("reglen"), funcpoints.vars.end());
	EXPECT_NE(funcpoints.vars.find("fcode"), funcpoints.vars.end());

	libxcom::OpValue reg = funcpoints.vars.at("reg");
	libxcom::OpValue reglen = funcpoints.vars.at("reglen");
	libxcom::OpValue fcode = funcpoints.vars.at("fcode");
	reg.Show();
	reglen.Show();
	fcode.Show();
	EXPECT_EQ(reg, libxcom::OpValue(static_cast<uint16_t>(0000)));
	EXPECT_EQ(reglen, libxcom::OpValue(static_cast<int8_t>(2)));
	EXPECT_EQ(fcode, libxcom::OpValue(static_cast<int8_t>(3)));
}

TEST_F(XComParserTest, LoadXComFileFunctions2)
{
	std::shared_ptr<protocol::XComNode> xcomNode =
		xcomParser_.GetXComNode("P056934A925C21000T");
	const FuncParam_t &funcpoints = xcomNode->GetFuncParam("12L");
	EXPECT_EQ(funcpoints.flow, "read");
	EXPECT_EQ(funcpoints.resultExpr->ToExprString(), "$bcd($data,0,4)*0.001");
	EXPECT_EQ(funcpoints.vars.size(), 2);

	EXPECT_EQ(funcpoints.vars.at("seq").As<uint32_t>(), 0x1f9001);
	EXPECT_EQ(funcpoints.vars.at("fcode").As<uint8_t>(), 0x10);

	libxcom::OpValue seq = funcpoints.vars.at("seq");
	libxcom::OpValue fcode = funcpoints.vars.at("fcode");
	seq.Show();
	fcode.Show();
}
} // namespace protocol

int main(int argc, char *argv[])
{
	utils::set_enable(true);
	::testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}